/**
 * Created by Admin on 30.12.2014.
 */

var GlShader = (function ($) {

    var ATTRIBUTES_VERTEX_POSITION = GlColoredSceneObject.ATTRIBUTES.VERTEX_POSITION;

    var MATRIX_UNIFORMS = [
        GlColoredSceneObject.UNIFORMS.MV_MATRIX,
        GlColoredSceneObject.UNIFORMS.P_MATRIX
    ];

    var CLICK_UNIFORMS = [
        "clickRgba",
        "click"
    ];

    var GlShader = $.inherit({

        options: {
            onShaderCreationFailed: $.noop
        },
        program: null,
        attributes: null,
        uniforms: null,
        gl: null,

        _getShader: function (str, glShader) {
            var gl = this.gl;
            var shader = gl.createShader(glShader);
            gl.shaderSource(shader, str);
            gl.compileShader(shader);
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                throw new Error($.format("SHADER {0}\n\n{1}\n\n{2}", glShader, gl.getShaderInfoLog(shader), str));
            }
            return shader;
        },

        _prepareProgram: function (rawProgram) {
            return rawProgram;
            //return rawProgram.replace("\n", " ");
        },

        __constructor: function (glShaderResources, gl, options) {
            this.options = $.extend({}, this.options, options);
            this.gl = gl;

            var glShader = this;
            var fragmentShader = glShaderResources.result.result[GlShader.FRAGMENT];
            var vertexShader = glShaderResources.result.result[GlShader.VERTEX];

            var shaderProgram = this.program = gl.createProgram();

            gl.attachShader(shaderProgram, this._getShader(this._prepareProgram(vertexShader.result), gl.VERTEX_SHADER));
            gl.attachShader(shaderProgram, this._getShader(this._prepareProgram(fragmentShader.result), gl.FRAGMENT_SHADER));
            gl.linkProgram(shaderProgram);

            if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
                this.options.onShaderCreationFailed();
                return;
            }

            gl.useProgram(shaderProgram);
            var metaData = glShaderResources.metaData;
            this.attributes = {};
            $.each(metaData.attributes, function (_, attribute) {
                glShader.attributes[attribute] = gl.getAttribLocation(shaderProgram, attribute);
                gl.enableVertexAttribArray(glShader.attributes[attribute]);
            });

            this.uniforms = {};
            $.each(metaData.uniforms, function (_, uniform) {
                glShader.uniforms[uniform] = gl.getUniformLocation(shaderProgram, uniform);
            });
        }

    }, {
        SHADERS_PATH: "shaders",
        VERTEX: "vertex",
        FRAGMENT: "fragment",

        COMMON_SHADERS: {

            SIMPLE: {
                name: "simple",
                attributes: [
                    ATTRIBUTES_VERTEX_POSITION,
                    GlColoredSceneObject.ATTRIBUTES.VERTEX_COLOR
                ],
                uniforms: [].concat(CLICK_UNIFORMS, MATRIX_UNIFORMS)
            },

            CLICK: {
                name: "click",
                attributes: [
                    ATTRIBUTES_VERTEX_POSITION
                ],
                uniforms: [].concat(["uRgba"], MATRIX_UNIFORMS)
            },

            SURF: {
                name: "surf",
                attributes: ["aPointCoordinate"],
                uniforms: [].concat([
                    "xMin", "xMax",
                    "yMin", "yMax",
                    "zMin", "zMax"
                ], [
                    "left", "right",
                    "bottom", "top",
                    "front", "back"
                ], CLICK_UNIFORMS, MATRIX_UNIFORMS)
            }
        }
    });
    return GlShader;

})(window["jQuery"]);